home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xarchie-2.0.9
/
FWF
/
FileChooser
/
FChooser.c
next >
Wrap
C/C++ Source or Header
|
1995-06-18
|
28KB
|
894 lines
/*
* FChooser.c : A widget for choosing a file
*
* George Ferguson, ferguson@cs.rochester.edu, 21 Jan 1993.
* Last update: 12 May 1993.
*
* This code is derived from the FileSelector widget by Brian Totty,
* hence the following copyright applies:
*
* Copyright 1990,1991,1992 Brian Totty
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appears in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Brian Totty or
* University of Illinois not be used in advertising or publicity
* pertaining to distribution of the software without specific, written
* prior permission. Brian Totty and University of Illinois make no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* Brian Totty and University of Illinois disclaim all warranties with
* regard to this software, including all implied warranties of
* merchantability and fitness, in no event shall Brian Totty or
* University of Illinois be liable for any special, indirect or
* consequential damages or any damages whatsoever resulting from loss of
* use, data or profits, whether in an action of contract, negligence or
* other tortious action, arising out of or in connection with the use or
* performance of this software.
*
* Author:
* Brian Totty
* Department of Computer Science
* University Of Illinois at Urbana-Champaign
* 1304 West Springfield Avenue
* Urbana, IL 61801
*
* totty@cs.uiuc.edu
*
*/
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/IntrinsicP.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/cursorfont.h>
#include <X11/CompositeP.h>
#include <X11/Composite.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/List.h>
#include <DirMgr.h>
#include <FChooserP.h>
#include <FChooser.h>
#if defined(SYSV) || defined(SVR4)
# ifndef __sgi
# ifndef getwd
# define getwd(path) getcwd(path, MAXPATHLEN)
# endif
# endif
#endif
/*---------------------------------------------------------------------------*
I N T E R N A L R O U T I N E S
*---------------------------------------------------------------------------*/
#if (!NeedFunctionPrototypes)
static void Initialize();
static void Realize();
static void Destroy();
static void Resize();
static Boolean SetValues();
static XtGeometryResult GeometryManager();
static void ChildrenCreate();
static void ChildrenRealize();
static void ChildrenUpdate();
static void DirectoryCallback();
static void FileCallback();
static void SelectFileByIndex();
static Boolean SelectFileByName();
static void UnselectAll();
static void Notify();
static void GotoDeepestLegalDirectory();
static void UpdateLists();
static void Chdir();
#else
static void Initialize(Widget request, Widget new);
static void Realize(Widget w, XtValueMask *valueMask,
XSetWindowAttributes *attrs);
static void Destroy(XfwfFileChooserWidget fcw);
static void Resize(Widget w);
static Boolean SetValues(Widget current, Widget request, Widget new);
static XtGeometryResult GeometryManager(Widget w,
XtWidgetGeometry *request,
XtWidgetGeometry *reply);
static void ChildrenCreate(XfwfFileChooserWidget fcw);
static void ChildrenRealize(XfwfFileChooserWidget fcw);
static void ChildrenUpdate(XfwfFileChooserWidget fcw);
static void DirectoryCallback(Widget w, XtPointer client_data,
XtPointer call_data);
static void FileCallback(Widget w, XtPointer client_data,
XtPointer call_data);
static void SelectFileByIndex(XfwfFileChooserWidget fcw, int index);
static Boolean SelectFileByName(XfwfFileChooserWidget fcw, char *name);
static void UnselectAll(XfwfFileChooserWidget fcw);
static void Notify(XfwfFileChooserWidget fcw);
static void GotoDeepestLegalDirectory(XfwfFileChooserWidget fcw);
static void UpdateLists(XfwfFileChooserWidget fcw);
static void Chdir(XfwfFileChooserWidget fcw);
#endif
/*---------------------------------------------------------------------------*
R E S O U R C E I N I T I A L I Z A T I O N
*---------------------------------------------------------------------------*/
#define FCFieldOffset(FIELD) XtOffset(XfwfFileChooserWidget,fileChooser.FIELD)
#define CoreFieldOffset(FIELD) XtOffset(Widget,core.FIELD)
static XtResource resources[] = {
{ XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
CoreFieldOffset(width), XtRString, "500" },
{ XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
CoreFieldOffset(height), XtRString, "250" },
{ XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
CoreFieldOffset(background_pixel), XtRString, "white" },
{ XtNcurrentDirectory, XtCPathname, XtRString, sizeof(String),
FCFieldOffset(current_dir), XtRString, NULL },
{ XtNcurrentFile, XtCFilename, XtRString, sizeof(String),
FCFieldOffset(current_file), XtRString, NULL },
{ XtNcallback, XtCCallback, XtRCallback,
sizeof(XtCallbackList), FCFieldOffset(callbacks), XtRCallback, NULL},
{XtNsortMode, XtCValue, XtRInt, sizeof(int),
FCFieldOffset(sort_mode), XtRString, "2"},
{XtNpattern, XtCFile, XtRString, sizeof(String),
FCFieldOffset(pattern), XtRString, NULL},
};
#undef FCFieldOffset
#undef CoreFieldOffset
/*---------------------------------------------------------------------------*
C L A S S A L L O C A T I O N
*---------------------------------------------------------------------------*/
XfwfFileChooserClassRec xfwfFileChooserClassRec = {
{
/* superclass */ (WidgetClass)&compositeClassRec,
/* class_name */ "XfwfFileChooser",
/* widget_size */ sizeof(XfwfFileChooserRec),
/* class_initialize */ NULL,
/* class_part_initialize*/ NULL,
/* class_inited */ FALSE,
/* initialize */ (XtInitProc)Initialize,
/* initialize_hook */ NULL,
/* realize */ (XtRealizeProc)Realize,
/* actions */ NULL,
/* num_actions */ 0,
/* resources */ resources,
/* resource_count */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ (XtWidgetProc)Destroy,
/* resize */ (XtWidgetProc)Resize,
/* expose */ XtInheritExpose,
/* set_values */ (XtSetValuesFunc)SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ NULL,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ XtInheritDisplayAccelerator,
/* extension */ NULL
}, /* Core Part */
{
/* geometry_manager */ GeometryManager,
/* change_managed */ XtInheritChangeManaged,
/* insert_child */ XtInheritInsertChild,
/* delete_child */ XtInheritDeleteChild,
/* extension */ NULL
}, /* Composite Part */
{
/* no extra class data */ 0
} /* FileSelector Part */
};
WidgetClass xfwfFileChooserWidgetClass =
(WidgetClass)&xfwfFileChooserClassRec;
/*---------------------------------------------------------------------------*
E X P O R T E D M E T H O D S
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
Initialize()
This procedure is called by the X toolkit to initialize
the FileChooser widget instance. The hook to this routine is in the
initialize part of the core part of the class.
*---------------------------------------------------------------------------*/
/* ARGSUSED */
static void
Initialize(request,new)
Widget request,new;
{
XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)new;
char *str,*initial_file,path[MAXPATHLEN + 2];
static char *star = "*";
FCBusyCursor(fcw) = XCreateFontCursor(XtDisplay(fcw),XC_watch);
FCDirMenu(fcw) = NULL;
FCDirMenuButton(fcw) = NULL;
FCFileList(fcw) = NULL;
FCDirMgr(fcw) = NULL;
FCFileNames(fcw) = NULL;
FCNumFileNames(fcw) = 0;
FCDirNames(fcw) = NULL;
FCNumDirNames(fcw) = 0;
str = (char *)XtCalloc((MAXPATHLEN + 2),sizeof(char));
if (FCCurrentDirectory(fcw) != NULL) { /* User Specified Path */
strcpy(str,FCCurrentDirectory(fcw));
} else {
getwd(path);
strcpy(str,path);
}
FCCurrentDirectory(fcw) = str;
str = (char *)XtCalloc((MAXPATHLEN + 2),sizeof(char));
initial_file = FCCurrentFile(fcw);
FCCurrentFile(fcw) = str;
if (FCCorePart(request)->width <= 0)
FCCorePart(new)->width = 500;
if (FCCorePart(request)->height <= 0)
FCCorePart(new)->height = 200;
if (FCPattern(fcw) == NULL)
FCPattern(fcw) = star;
FCPattern(fcw) = XtNewString(FCPattern(fcw));
ChildrenCreate(fcw);
GotoDeepestLegalDirectory(fcw);
if (initial_file)
SelectFileByName(fcw,initial_file);
} /* End Initialize */
/*---------------------------------------------------------------------------*
Realize()
This function is called to realize a FileChooser widget.
*---------------------------------------------------------------------------*/
static void Realize(w,valueMask,attrs)
Widget w;
XtValueMask *valueMask;
XSetWindowAttributes *attrs;
{
XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)w;
XtCreateWindow(w,InputOutput,(Visual *)CopyFromParent,*valueMask,attrs);
ChildrenRealize(fcw);
ChildrenUpdate(fcw);
Resize(w);
Notify(fcw);
} /* End Realize */
/*---------------------------------------------------------------------------*
Destroy()
This function is called to destroy a FileChooser widget.
*---------------------------------------------------------------------------*/
static void
Destroy(fcw)
XfwfFileChooserWidget fcw;
{
int i;
XtFree(FCCurrentDirectory(fcw));
XtFree(FCCurrentFile(fcw));
XtFree(FCPattern(fcw));
if (FCFileNames(fcw) != NULL) {
for (i=0; i < FCNumFileNames(fcw); i++)
XtFree(FCFileNames(fcw)[i]);
XtFree((char *)FCFileNames(fcw));
}
if (FCDirNames(fcw) != NULL) {
for (i=0; i < FCNumDirNames(fcw); i++)
XtFree(FCDirNames(fcw)[i]);
XtFree((char *)FCDirNames(fcw));
}
} /* End Destroy */
/*---------------------------------------------------------------------------*
Resize()
This function is called to resize a FileChooser widget.
*---------------------------------------------------------------------------*/
static void
Resize(w)
Widget w;
{
XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)w;
ChildrenUpdate(fcw);
} /* End Resize */
/*---------------------------------------------------------------------------*
SetValues()
This function is the external interface for setting resources.
*---------------------------------------------------------------------------*/
/* ARGSUSED */
static Boolean
SetValues(current,request,new)
Widget current,request,new;
{
XfwfFileChooserWidget fcw_current = (XfwfFileChooserWidget)current;
XfwfFileChooserWidget fcw_new = (XfwfFileChooserWidget)new;
if (FCCurrentDirectory(fcw_current) != FCCurrentDirectory(fcw_new)){
strcpy(FCCurrentDirectory(fcw_current),FCCurrentDirectory(fcw_new));
FCCurrentDirectory(fcw_new) = FCCurrentDirectory(fcw_current);
Chdir(fcw_new);
}
if (FCCurrentFile(fcw_current) != FCCurrentFile(fcw_new)) {
char *new_name;
new_name = FCCurrentFile(fcw_new);
FCCurrentFile(fcw_new) = FCCurrentFile(fcw_current);
SelectFileByName(fcw_new,new_name);
}
if (FCPattern(fcw_current) != FCPattern(fcw_new)) {
XtFree(FCPattern(fcw_current));
FCPattern(fcw_new) = XtNewString(FCPattern(fcw_current));
Chdir(fcw_new);
}
if (FCSortMode(fcw_current) != FCSortMode(fcw_new)) {
Chdir(fcw_new);
}
return(False);
} /* End SetValues() */
/*---------------------------------------------------------------------------*
GeometryManager(w,request,reply)
This routine acts as the geometry_manager method for the
FileChooser widget. It is called when a child wants to
resize/reposition itself.
Currently, we allow all requests.
*---------------------------------------------------------------------------*/
/* ARGSUSED */
static XtGeometryResult
GeometryManager(w,request,reply)
Widget w;
XtWidgetGeometry *request;
XtWidgetGeometry *reply;
{
return(XtGeometryYes);
} /* End GeometryManager */
/*---------------------------------------------------------------------------*
L O C A L R O U T I N E S
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
ChildrenCreate(fcw)
This routine creates the initial child widgets for the
file selector widget and places them in the widget fcw.
No placement or resizing is done. That is done by
ChildrenUpdate().
*---------------------------------------------------------------------------*/
static void
ChildrenCreate(fcw)
XfwfFileChooserWidget fcw;
{
Arg args[2];
static char *str = NULL;
XtSetArg(args[0],XtNmenuName,FC_DIR_MENU_NAME);
FCDirMenuButton(fcw) =
XtCreateManagedWidget(FC_DIR_MENU_BUTTON_NAME,menuButtonWidgetClass,
(Widget)fcw,args,1);
XtSetArg(args[0],XtNallowVert,True);
XtSetArg(args[1],XtNforceBars,True);
FCFileViewport(fcw) =
XtCreateManagedWidget(FC_FILE_VIEWPORT_NAME,viewportWidgetClass,
(Widget)fcw,args,2);
XtSetArg(args[0],XtNlist,&str);
XtSetArg(args[1],XtNverticalList,True);
FCFileList(fcw) = XtCreateManagedWidget(FC_FILE_LIST_NAME,listWidgetClass,
FCFileViewport(fcw),args,2);
XtAddCallback(FCFileList(fcw),XtNcallback,
(XtCallbackProc)FileCallback,(XtPointer)fcw);
} /* End ChildrenCreate */
/*---------------------------------------------------------------------------*
ChildrenRealize(fcw)
This routine realizes the child widgets. The widgets must
already have been created and initialized. Their coordinates
should already have been set.
*---------------------------------------------------------------------------*/
static void
ChildrenRealize(fcw)
XfwfFileChooserWidget fcw;
{
XtRealizeWidget(FCDirMenuButton(fcw));
XtRealizeWidget(FCFileViewport(fcw));
XtRealizeWidget(FCFileList(fcw));
} /* End ChildrenRealize */
/*---------------------------------------------------------------------------*
ChildrenUpdate(fcw)
This routine takes a FileChooser widget fcw and updates
the child widgets by recalculating their coordinates based
on the current size of the FileChooser, and setting the
appropriate resources.
We go to some trouble to get something useful displayed in the
FCDirMenuButton(fcw) if the current directory name is too long
to fit in the button. It would be nice if the "justify" resource
of the MenuButton widget did this, but...
*---------------------------------------------------------------------------*/
static void
ChildrenUpdate(fcw)
XfwfFileChooserWidget fcw;
{
Dimension w,h;
int gap;
Dimension menuButtonW,menuButtonH,fileListW,fileListH;
Position menuButtonX,menuButtonY,fileListX,fileListY;
XtWidgetGeometry parent_idea,child_idea;
Arg args[3];
XFontStruct *fs;
char *label;
Dimension intw;
if (!XtIsRealized((Widget)fcw)) {
return;
}
w = CoreWidth(fcw);
h = CoreHeight(fcw);
gap = 3;
/* Get The Child Widgets Current Widths And Heights */
/* (although we don't actually use the existing values... */
menuButtonW = CoreWidth(FCDirMenuButton(fcw));
menuButtonH = CoreHeight(FCDirMenuButton(fcw));
fileListW = CoreWidth(FCFileList(fcw));
fileListH = CoreHeight(FCFileList(fcw));
/* Adjust Widths */
menuButtonW = w;
fileListW = w;
/* Adjust menu button label if too small */
/* It would be nice if the "justify" resource of MenuButton did this... */
XtSetArg(args[0],XtNinternalWidth,&intw);
XtSetArg(args[1],XtNfont,&fs);
XtGetValues(FCDirMenuButton(fcw),args,2);
label = FCCurrentDirectory(fcw);
if (XTextWidth(fs,label,strlen(label)) > (int)(menuButtonW-intw)) {
char newLabel[MAXPATHLEN];
while (*label && XTextWidth(fs,label,strlen(label)) >
(int)(menuButtonW-intw)) {
label += 1;
}
if (*label)
label += 1;
strcpy(newLabel,"<");
strcat(newLabel,label);
XtSetArg(args[0],XtNlabel,newLabel);
XtSetValues(FCDirMenuButton(fcw),args,1);
}
/* Adjust Heights */
fileListH = h - menuButtonH - gap;
/* Listen To Child Height Request For List */
parent_idea.request_mode = CWWidth | CWHeight;
parent_idea.width = fileListW;
parent_idea.height = fileListH;
XtQueryGeometry(FCFileList(fcw),&parent_idea,&child_idea);
if ((child_idea.request_mode & CWHeight) &&
(child_idea.height < parent_idea.height)) {
fileListH = child_idea.height;
}
/* Vertical Positions */
menuButtonY = 0;
fileListY = menuButtonH + gap;
/* Horizontal Positions */
menuButtonX = 0;
fileListX = 0;
/* Move them */
XtMoveWidget(FCDirMenuButton(fcw),menuButtonX,menuButtonY);
XtMoveWidget(FCFileViewport(fcw),fileListX,fileListY);
/* Resize them */
XtResizeWidget(FCDirMenuButton(fcw),menuButtonW,menuButtonH,
CoreBorderWidth(FCDirMenuButton(fcw)));
XtResizeWidget(FCFileViewport(fcw),fileListW,fileListH,
CoreBorderWidth(FCFileViewport(fcw)));
} /* End ChildrenUpdate */
/*---------------------------------------------------------------------------*
I N T E R N A L C A L L B A C K S
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
DirectoryCallback(w,client_data,call_data)
This is called when the user selects an ancestor directory from
the menu. The argument "w" is the selected object (hence the two
calls to XtParent()) and "client_data" is it's index in the menu.
*---------------------------------------------------------------------------*/
/*ARGSUSED*/
static void
DirectoryCallback(w,client_data,call_data)
Widget w;
XtPointer client_data; /* index */
XtPointer call_data; /* not used */
{
int index = (int)client_data;
XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)XtParent(XtParent(w));
int i;
strcpy(FCCurrentDirectory(fcw),"/");
for (i = 1; i <= index; i++) {
strcat(FCCurrentDirectory(fcw),FCDirNames(fcw)[i]);
strcat(FCCurrentDirectory(fcw),"/");
}
Chdir(fcw);
} /* End DirectoryCallback */
/*---------------------------------------------------------------------------*
FileCallback(w,client_data,call_data)
This is called when the user selects a file in the fileList.
The argument "client_data" is the FileChooser widget, "call_data"
is a pointer to the standard List widget callback information.
*---------------------------------------------------------------------------*/
/*ARGSUSED*/
static void
FileCallback(w,client_data,call_data)
Widget w;
XtPointer client_data; /* fcw */
XtPointer call_data; /* return struct */
{
XfwfFileChooserWidget fcw = (XfwfFileChooserWidget)client_data;
XawListReturnStruct *ret = (XawListReturnStruct *)call_data;
if (ret->list_index == -1) {
UnselectAll(fcw); /* Click On Blank Space */
Notify(fcw);
} else {
SelectFileByIndex(fcw,ret->list_index);
}
} /* End FileCallback */
/*---------------------------------------------------------------------------*
I N T E R N A L S U P P O R T R O U T I N E S
*---------------------------------------------------------------------------*/
static void
SelectFileByIndex(fcw,index)
XfwfFileChooserWidget fcw;
int index;
{
DirEntry *dir_entry;
DirectoryMgrGotoItem(FCDirMgr(fcw),index);
if ((dir_entry=DirectoryMgrCurrentEntry(FCDirMgr(fcw))) == NULL) {
fprintf(stderr,"SelectFileByIndex: Entry %d invalid\n",index);
XtAppErrorMsg(XtWidgetToApplicationContext((Widget)fcw),
"selectFailed","SelectFileByIndex","XfwfError",
"FileChooser: SelectFileByIndex failed.",
(String*)NULL,(Cardinal*)NULL);
}
if (DirEntryIsDir(dir_entry) || DirEntryIsDirectoryLink(dir_entry)) {
strcat(FCCurrentDirectory(fcw),DirEntryFileName(dir_entry));
Chdir(fcw);
} else if (!DirEntryIsBrokenLink(dir_entry)) { /* File */
strcpy(FCCurrentFile(fcw),DirEntryFileName(dir_entry));
XawListHighlight(FCFileList(fcw),index);
Notify(fcw);
} else { /* Broken Link */
XBell(XtDisplay(fcw),0);
UnselectAll(fcw);
}
} /* End SelectFileByIndex */
static Boolean
SelectFileByName(fcw,name)
XfwfFileChooserWidget fcw;
char *name;
{
if (DirectoryMgrGotoNamedItem(FCDirMgr(fcw),name) == FALSE) {
return(False);
}
SelectFileByIndex(fcw,DirectoryMgrCurrentIndex(FCDirMgr(fcw)));
return(True);
} /* End SelectFileByName */
static void
UnselectAll(fcw)
XfwfFileChooserWidget fcw;
{
Boolean selected = FCCurrentFile(fcw)[0] != '\0';
FCCurrentFile(fcw)[0] = '\0';
XawListUnhighlight(FCFileList(fcw));
if (selected)
Notify(fcw);
} /* End UnselectAll */
static void
Notify(fcw)
XfwfFileChooserWidget fcw;
{
XfwfFileChooserReturnStruct ret;
if (FCCurrentFile(fcw)[0] != '\0') {
ret.directory = FCCurrentDirectory(fcw);
ret.file = FCCurrentFile(fcw);
} else {
ret.directory = NULL;
ret.file = NULL;
}
XtCallCallbacks((Widget)fcw,XtNcallback,(XtPointer)&ret);
} /* End Notify */
/*---------------------------------------------------------------------------*
GotoDeepestLegalDirectory(fcw)
This function takes a FileChooser widget <fcw> and modifies the
directory string in FCCurrentDirectory(fcw) to be the deepest
legal directory above the string. Partial or incorrect directory
names are stripped starting at the end.
It then calls UpdateLists() to reset the information dislayed in
the FileChooser.
*---------------------------------------------------------------------------*/
static void
GotoDeepestLegalDirectory(fcw)
XfwfFileChooserWidget fcw;
{
char *dir,*end;
char temp[MAXPATHLEN + 2];
dir = FCCurrentDirectory(fcw);
for (end=dir; *end != '\0'; ++end)
/*EMPTY*/;
while (1) {
if (DirectoryPathExpand(dir,temp) == NULL) {
while (*end != '/' && end != dir) {
end -= 1;
}
*end = '\0';
} else {
strcpy(FCCurrentDirectory(fcw),temp);
break;
}
}
UnselectAll(fcw);
UpdateLists(fcw);
} /* End GotoDeepestLegalDirectory */
/*---------------------------------------------------------------------------*
UpdateLists(fcw)
This routine resets the information displayed in a FileChooser
widget by doing the following:
1. It changes the cursor to the value of the "busyCursor" resource.
2. The old directory manager (FCDirMgr(fcw)) is closed and a
new one opened based on the value of FCCurrentDirectory(fcw).
3. Any old string arrays are freed, and any existing directory
menu is destroyed.
4. A new array of strings (FCFileNames(fcw)) is allocated and filled
with the names of the files in the directory, then this array
is used to set what is displayed in the FCFileList(fcw) widget.
5. A new array of strings (FCDirNames(fcw)) is allocated and filled
with the names of the ancestor directories. These are also used
to create a new FCDirMenu(fcw), and the label FCDirMenuButton(fcw)
is set to the name of the directory.
6. Finally, the cursor is restored.
*---------------------------------------------------------------------------*/
static void
UpdateLists(fcw)
XfwfFileChooserWidget fcw;
{
Arg args[1];
int i,count;
char *dir,*start;
DirEntry *dir_entry;
char temp[MAXPATHLEN + 2];
Widget menuItem;
if (XtIsRealized((Widget)fcw)) {
/* This is puke-ola. */
XDefineCursor(XtDisplay(fcw),XtWindow(fcw),FCBusyCursor(fcw));
XDefineCursor(XtDisplay(fcw),XtWindow(FCFileList(fcw)),
FCBusyCursor(fcw));
XDefineCursor(XtDisplay(fcw),XtWindow(FCDirMenuButton(fcw)),
FCBusyCursor(fcw));
XFlush(XtDisplay(fcw));
}
if (FCDirMgr(fcw))
DirectoryMgrClose(FCDirMgr(fcw));
FCDirMgr(fcw) = DirectoryMgrSimpleOpen(FCCurrentDirectory(fcw),
FCSortMode(fcw),FCPattern(fcw));
/* Throw away old info */
if (FCFileNames(fcw) != NULL) {
for (i = 0; i < FCNumFileNames(fcw); i++)
XtFree(FCFileNames(fcw)[i]);
XtFree((char *)FCFileNames(fcw));
}
if (FCDirNames(fcw) != NULL) {
for (i = 0; i < FCNumDirNames(fcw); i++)
XtFree(FCDirNames(fcw)[i]);
XtFree((char *)FCDirNames(fcw));
}
if (FCDirMenu(fcw) != NULL)
XtDestroyWidget(FCDirMenu(fcw));
/* Count how many files and dirs we have now */
FCNumFileNames(fcw) = DirectoryMgrFilteredCount(FCDirMgr(fcw));
FCNumDirNames(fcw) = 1;
for (dir=FCCurrentDirectory(fcw)+1; *dir != '\0'; dir++) {
if (*dir == '/')
FCNumDirNames(fcw) += 1;
}
/* Make the array of filenames and set the fileList widget */
FCFileNames(fcw) = (char **)XtCalloc(FCNumFileNames(fcw)+1,sizeof(char *));
for (i=0; i < FCNumFileNames(fcw); i++) {
dir_entry = DirectoryMgrNextEntry(FCDirMgr(fcw));
if (dir_entry == NULL)
XtError("Inconsistent Directory");
strcpy(temp,DirEntryFileName(dir_entry));
if (DirEntryIsDir(dir_entry))
strcat(temp,"/");
else if (DirEntryIsBrokenLink(dir_entry))
strcat(temp," X");
else if (DirEntryIsDirectoryLink(dir_entry))
strcat(temp,"/");
else if (DirEntryIsSymLink(dir_entry))
strcat(temp," @");
FCFileNames(fcw)[i] = XtNewString(temp);
}
FCFileNames(fcw)[i] = NULL;
XawListChange(FCFileList(fcw),FCFileNames(fcw),FCNumFileNames(fcw),0,True);
/* Make the array of dirnames and build a new dirMenu widget */
FCDirNames(fcw) = (char **)XtCalloc(FCNumDirNames(fcw)+1,sizeof(char *));
FCDirNames(fcw)[0] = XtNewString("/");
FCDirMenu(fcw) = XtCreatePopupShell(FC_DIR_MENU_NAME,simpleMenuWidgetClass,
(Widget)fcw,NULL,0);
menuItem = XtCreateManagedWidget("/",smeBSBObjectClass,FCDirMenu(fcw),
NULL,0);
XtAddCallback(menuItem,XtNcallback,DirectoryCallback,(XtPointer)0);
start = FCCurrentDirectory(fcw);
for (i = 1; i < FCNumDirNames(fcw); i++) {
while (*start != '\0' && *start == '/')
start += 1;
count = 0;
while (*start != '\0' && *start != '/')
temp[count++] = *start++;
temp[count] = '\0';
FCDirNames(fcw)[i] = XtNewString(temp);
XtSetArg(args[0],XtNlabel,temp);
menuItem = XtCreateManagedWidget("dirMenuItem",smeBSBObjectClass,
FCDirMenu(fcw),args,1);
XtAddCallback(menuItem,XtNcallback,DirectoryCallback,(XtPointer)i);
}
XtSetArg(args[0],XtNlabel,FCCurrentDirectory(fcw));
XtSetValues(FCDirMenuButton(fcw),args,1);
if (XtIsRealized((Widget)fcw)) {
XUndefineCursor(XtDisplay(fcw),XtWindow(fcw));
XUndefineCursor(XtDisplay(fcw),XtWindow(FCFileList(fcw)));
XUndefineCursor(XtDisplay(fcw),XtWindow(FCDirMenuButton(fcw)));
}
} /* End UpdateLists */
static void Chdir(fcw)
XfwfFileChooserWidget fcw;
{
GotoDeepestLegalDirectory(fcw);
ChildrenUpdate(fcw);
} /* End Chdir */
/*---------------------------------------------------------------------------*
E X T E R N A L R O U T I N E S
*---------------------------------------------------------------------------*/
void
XfwfFileChooserChangeDirectory(fcw,dir)
XfwfFileChooserWidget fcw;
char *dir;
{
strcpy(FCCurrentDirectory(fcw),dir);
Chdir(fcw);
} /* End XfwfFileChooserChangeDirectory */
void
XfwfFileChooserRefresh(fcw)
XfwfFileChooserWidget fcw;
{
XfwfFileChooserChangeDirectory(fcw,".");
} /* End XfwfFileChooserRefresh */
char *
XfwfFileChooserCurrentDirectory(fcw)
XfwfFileChooserWidget fcw;
{
return(FCCurrentDirectory(fcw));
} /* End XfwfFileChooserCurrentDirectory */
char *
XfwfFileChooserCurrentFile(fcw)
XfwfFileChooserWidget fcw;
{
return(FCCurrentFile(fcw));
} /* End XfwfFileChooserCurrentFile */